#ifndef UHM_DISCRETE_IO_STREAM2MESH_HXX_
#define UHM_DISCRETE_IO_STREAM2MESH_HXX_

namespace uhm {

  template<class M_> Bool_ stream2mesh(std::istream &stream, M_ &mesh) {
    time_in("uhm:: stream2mesh",UHM_TIME_LEVEL_INTERNAL);

    skip_comment(stream);

    std::string format;
    stream >> format;

    if (get_verbose())
      std::cout << "Reading format is " << format << std::endl;

    // --------- Format check
    if ( format != "STREAM" ) {
      UHM_ERROR(false, ">> Format is NOT STREAM");
    }

    if (get_verbose())
      std::cout << std::endl;

    // --------- Node spec
    Int_ n_node_var, is_high;
    skip_comment(move_to_endl(stream));
    stream >> n_node_var >> is_high;

    if (get_verbose())
      std::cout << "n_nodes_var : " << n_node_var 
                << ", is_higher node : "<< is_high 
                << std::endl;
    
    // --------- Reading nodes
    Int_ n_nodes;
    skip_comment(move_to_endl(stream));
    stream >> n_nodes;

    if (get_verbose())
      std::cout << "n_nodes : " << n_nodes << std::endl;

    for (Int_ i_nd=0;i_nd<n_nodes;++i_nd) {
      typename M_::_Id_Nd_ nd;
      for (Int_ i_id=0;i_id<n_node_var;++i_id) {
        Int_ var;
        skip_comment(move_to_endl(stream));
        stream >> var;
        
        nd.set_id(i_id, var);

        if (get_verbose())
          std::cout << var << "  " ;
      }

      Int_ dof = 1;  
      if (is_high) {
        stream >> dof ;
        if (get_verbose())
          std::cout << ", dof : " << dof;
      }

      Int_ kind; stream >> kind;
      if (get_verbose())
        std::cout << ", kind : " << kind << std::endl;

      nd.set_dof(dof);
      typename M_::Node_* nod = mesh.add_node(nd, kind);

    }

    if (get_verbose())
      std::cout << std::endl;

    // --------- Element spec
    Int_ n_element_var;
    skip_comment(move_to_endl(stream));
    stream >> n_element_var;
    
    if (get_verbose())
      std::cout << "n_element_var : " << n_element_var 
                << " (setting 0, we do not read element id)" << std::endl;

    // --------- Reading elements
    Int_ n_elements;
    skip_comment(move_to_endl(stream));
    stream >> n_elements;

    if (get_verbose())
      std::cout << "n_elements : " << n_elements << std::endl;

    typename M_::_Id_El_ el;      
    for (Int_ i_el=0;i_el<n_elements;++i_el) {
      typename M_::Element_* elt;

      if (n_element_var) {
        for (Int_ i_id=0;i_id<n_element_var;++i_id) {
          Int_ var;
          stream >> var;

          if (get_verbose())
            std::cout << var << ", " << std::endl;

          el.set_id(i_id, var);
        }
        
        if (get_verbose())
          std::cout << std::endl;

        elt = mesh.add_element(el);
      } {
        elt = mesh.add_element(el);
        ++el;
      }

      Int_ n_elt_nodes;
      skip_comment(move_to_endl(stream));
      stream >> n_elt_nodes;
      
      if (get_verbose())
        std::cout << "n_elt_nodes : " << n_elt_nodes << std::endl;

      elt->push_begin();
      for (Int_ i_nd=0;i_nd<n_elt_nodes;++i_nd) {
        typename M_::_Id_Nd_ nd;
        for (Int_ i_id=0;i_id<n_node_var;++i_id) {
          Int_ var;
          skip_comment(move_to_endl(stream));
          stream >> var;

          if (get_verbose())
            std::cout << var << "  " ;

          nd.set_id(i_id, var);
        }

        if (get_verbose())
          std::cout << std::endl;

        typename M_::Node_* nod = mesh.find_node(nd);
        elt->push(nod);
      }
      elt->push_end();
    }

    if (get_verbose())
      std::cout << "Reading mesh from file is done" << std::endl;
    
    time_out(UHM_TIME_LEVEL_INTERNAL);
    return true;
  }

}

#endif
